﻿/*----------------------------------------------------------------
    // Copyright (C) 2009 江苏华招网
    // 版权所有。 
    // 作者：李刚 
    //
    // 文件名：BasePage.cs
    // 文件功能描述：页面基类，处理系统页面权限
    // 创建标识：李刚 2009-03-17
    //
    // 修改标识：李刚 2009-03-18
    // 修改描述：在基类中处理权限控件的验证，不再向控件提供public方法
    //
    // 修改标识：李刚 2009-03-20
    // 修改描述：基类中对页面内EnableRBAC属性为False的控件不再注入验证事件，以减小服务器性能消耗
    //
    // 审核人：
    // 审核时间：
    // 审核说明：
 //----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HZ.Web;
using System.IO;
using HZ.DrugTrade.Model.Enum;

namespace HZ.DrugTrade.Web
{
    public class BasePage : System.Web.UI.Page
    {
        #region 私有成员
        /// <summary>
        /// 私有变量 页面所属的模块代码
        /// </summary>
        private string _ModuleNo = string.Empty;
        /// <summary>
        /// 进入页面需要的操作类型  默认的操作： OperateType.查看
        /// </summary>
        private string _OperateType = HZ.DrugTrade.Model.Enum.OperateType.查看.ToString();
        //private string _OperateType = string.Empty; 
        /// <summary>
        /// 返回页面
        /// </summary>
        private string _ReturnUrl = string.Empty;
        /// <summary>
        /// 序列化的查询条件
        /// </summary>
        private string _QueryCondition = "";
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public BasePage()
        {
            this.Load += new EventHandler(BasePage_Load);
            this.LoadComplete += new EventHandler(BasePage_LoadComplete);
        }

        /// <summary>
        /// 重载OnLoad 给带权限控件的Validate事件绑定验证方法
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            //将页面中所有继承IRbacControl的控件注册验证事件
            BindrbacValidateEvent(this.Page);
            base.OnLoad(e);
        }

        /// <summary>
        /// 重载OnPreRender 给带权限控件的 PreRender事件绑定验证方法
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            ////将页面中所有继承IRbacControl的控件注册呈现事件
            BindrbacPreRenderEvent(this.Page);
            base.OnPreRender(e);
        }

        /// <summary>
        /// 重写ProcessRequest
        /// </summary>
        /// <param name="context"></param>
        public override void ProcessRequest(HttpContext context)
        {
            //从浏览器重输入的URl 不做返回处理
            if (context.Request.UrlReferrer != null && context.Request[Constants.QUERYSTRING_RETURN_URL] == null)
            {
                //从菜单页面来 无需记录returnUrl
                if (context.Request.UrlReferrer.AbsolutePath.IndexOf("Default") != -1)
                {
                    base.ProcessRequest(context);
                }
                //两次停留在同一页面 则不做返回处理
                else if (context.Request.UrlReferrer.AbsolutePath != context.Request.Url.AbsolutePath)
                {
                    //去掉多余的returnUrl参数
                    int index = context.Request.UrlReferrer.PathAndQuery.IndexOf(Constants.QUERYSTRING_RETURN_URL);
                    string returnUrl = "";
                    if (index != -1)
                    {
                        //去掉多余的returnUrl参数
                        returnUrl = Constants.QUERYSTRING_RETURN_URL + "=" + HttpUtility.UrlEncode(context.Request.UrlReferrer.PathAndQuery.Substring(0, index - 1));
                    }
                    else
                    {
                        returnUrl = Constants.QUERYSTRING_RETURN_URL + "=" + HttpUtility.UrlEncode(context.Request.UrlReferrer.PathAndQuery);
                    }
                    //当前页面无参数的要使用 "?" 追加 returnRrl
                    if (context.Request.Url.Query != "")
                    {
                        context.Response.Redirect(context.Request.Url.PathAndQuery + "&" + returnUrl);
                    }
                    else
                    {
                        context.Response.Redirect(context.Request.Url.PathAndQuery + "?" + returnUrl);
                    }
                }
                else
                {
                    base.ProcessRequest(context);
                }
            }
            else
            {
                base.ProcessRequest(context);
            }
        }

        /// <summary>
        /// 重写render 将页面中脚本替换成 defer 使得js懒加载
        /// </summary>
        /// <param name="writer"></param>
        protected override void Render(HtmlTextWriter writer)
        {
            //string oldContent;
            //string newContent;
            //StringWriter stringWriter = new StringWriter();
            //HtmlTextWriter oldwriter = new HtmlTextWriter(stringWriter);
            //base.Render(oldwriter);

            //oldContent = stringWriter.ToString();
            //newContent = oldContent.Replace("type=\"text/javascript\">", "type=\"text/javascript\" defer>");
            //writer.Write(newContent);
            base.Render(writer);

        }

        #region 事件

        /// <summary>
        /// load事件处理，先于aspx页面Page_Load执行
        /// </summary>
        private void BasePage_Load(object sender, EventArgs e)
        {
            //检查页面执行权限
            CheckAuthority();
            //设置returnurl
            GetReturnUrl();
            //获取查询条件
            GetQueryCondition();
        }

        /// <summary>
        /// loadComplete事件处理
        /// </summary>
        private void BasePage_LoadComplete(object sender, EventArgs e)
        {
            //待实现...
        }

        /// <summary>
        /// 控件的PreRender事件处理 决定控件的呈现
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void control_PreRender(object sender, EventArgs e)
        {
            IRbacControl rbacCtrl = (IRbacControl)sender;
            WebControl control = (WebControl)sender;

            //根据控件所进行的操作 动态设定其呈现状态
            if (rbacCtrl.AttributeToControl == "Visible")
            {
                control.Visible = control.Visible && ValidateRight(rbacCtrl);
            }
            else
            {
                control.Enabled = control.Enabled && ValidateRight(rbacCtrl);
            }

        }

        /// <summary>
        /// 控件的Validate事件处理 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbacCtrl_Validate(object sender, EventArgs e)
        {
            IRbacControl rbacCtrl = (IRbacControl)sender;

            if (!ValidateRight(rbacCtrl))
            {
                //取消控件动作
                rbacCtrl.ActionCancel = true;
                //跳转到无权访问页面
                Page_NoPermission();
            }
            else
            {
                //记录控件操作日志
                this.ControlOperateLog(rbacCtrl);
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 检查页面执行权限
        /// </summary>
        private void CheckAuthority()
        {
            if (!ValidateSession())
            {
                //跳转到登陆页面
                Page_NoLogin();
            }
            if (!ValidatePageRight(this._ModuleNo))
            {

                //跳转到无权访问页面
                Page_NoPermission();
            }

        }

        /// <summary>
        /// 递归寻找控件 并注册验证事件 （验证事件在 click事件之前发生）
        /// </summary>
        /// <param name="ctrl"></param>
        /// <param name="strCommandName"></param>
        private void BindrbacValidateEvent(Control parent)
        {
            foreach (Control control in parent.Controls)
            {
                if (control.HasControls())
                {
                    BindrbacValidateEvent(control);
                }
                else if (control is IRbacControl)
                {
                    //将页面中继承IRbacControl的控件且启用权限控制的控件 注入验证事件
                    IRbacControl rbacCtrl = (IRbacControl)control;
                    if (rbacCtrl.EnableRBAC)
                    {
                        rbacCtrl.Validate += new EventHandler(rbacCtrl_Validate);
                    }
                }
            }
        }

        /// <summary>
        /// 递归寻找控件 并注册控件呈现事件
        /// </summary>
        /// <param name="parent"></param>
        private void BindrbacPreRenderEvent(Control parent)
        {
            foreach (Control control in parent.Controls)
            {
                if (control.HasControls())
                {
                    BindrbacPreRenderEvent(control);
                }
                else if (control is IRbacControl)
                {
                    //将页面中继承IRbacControl的控件且启用权限控制的控件 注入验证事件
                    IRbacControl rbacCtrl = (IRbacControl)control;
                    if (rbacCtrl.EnableRBAC)
                    {
                        control.PreRender += new EventHandler(control_PreRender);
                    }
                }
            }
        }

        /// <summary>
        /// 验证控件操作权限
        /// </summary>
        /// <returns></returns>
        private bool ValidateRight(IRbacControl rbacCtrl)
        {
            Control control = (Control)rbacCtrl;
            //如果控件的模块号为空 则集成页面的模块号
            if (rbacCtrl.ModuleNo == string.Empty)
            {
                rbacCtrl.ModuleNo = ((BasePage)control.Page).ModuleNo;
            }

            bool isHaveRight = true;
            if (rbacCtrl.EnableRBAC)
            {
                if (rbacCtrl.ModuleNo != "" && rbacCtrl.OperateType != "")
                {
                    isHaveRight = ValidateModuleRight(rbacCtrl.ModuleNo, rbacCtrl.OperateType);
                }
            }
            return isHaveRight;
        }

        /// <summary>
        /// 设置returnUrl
        /// </summary>
        private void GetReturnUrl()
        {
            if (HttpContext.Current.Request.QueryString[Constants.QUERYSTRING_RETURN_URL] != null)
            {
                int index = HttpContext.Current.Request.QueryString[Constants.QUERYSTRING_RETURN_URL].IndexOf(",");
                if (index == -1)
                {
                    this._ReturnUrl = HttpContext.Current.Request.QueryString[Constants.QUERYSTRING_RETURN_URL];

                }
                else
                {
                    this._ReturnUrl = HttpContext.Current.Request.QueryString[Constants.QUERYSTRING_RETURN_URL].Substring(0, index);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public string SetQueryCondition<T>(T obj)
        {
            this._QueryCondition = StringUtility.Compress(StringUtility.ConvertObjectToString(obj));
            return HttpUtility.UrlEncode(this._QueryCondition);

            //StringWriter sw = new StringWriter();
            //(new LosFormatter()).Serialize(sw, obj);
            //string hashkey = HZ.Fun.GetMd5(sw.ToString());
            //Session[hashkey] = obj;
            //return hashkey;

        }

        private void GetQueryCondition()
        {
            if (HttpContext.Current.Request.QueryString[Constants.QUERYSTRING_QUERY_CONDITION] != null)
            {
                string hashkey = HttpContext.Current.Request.QueryString[Constants.QUERYSTRING_QUERY_CONDITION];
                this._QueryCondition = hashkey;
            }
        }

        //记录控件操作日志
        private void ControlOperateLog(IRbacControl rbacCtrl)
        {
            Control control = (Control)rbacCtrl;
            //如果控件的模块号为空 则集成页面的模块号
            if (rbacCtrl.ModuleNo == string.Empty)
            {
                rbacCtrl.ModuleNo = ((BasePage)control.Page).ModuleNo;
            }

            //记录日志
            //模块为空不记录
            if (rbacCtrl.ModuleNo != "" && rbacCtrl.OperateType != "")
            {
                OperateLog(rbacCtrl.ModuleNo.ToString(), rbacCtrl.OperateType.ToString());
            }

        }

        /// <summary>
        /// 记录页面日志
        /// </summary>
        private void PageOperateLog()
        {
            //记录日志
            //模块为空 或者查看操作不记录
            if (this.ModuleNo != "" && this.PageOperateType != OperateType.查看.ToString())
            {
                OperateLog(this.ModuleNo.ToString(), this.PageOperateType.ToString());
            }
        }

        #endregion

        #region 业务逻辑接口 可修改部分

        /// <summary>
        /// 页面级权限判断
        /// </summary>
        /// <param name="strModuleName"></param>
        /// <returns></returns>
        private bool ValidatePageRight(string strModuleNo)
        {
            bool isHaveRight = true;
            if (strModuleNo != "")
            {
                isHaveRight = ValidateModuleRight(strModuleNo, this._OperateType);
            }
            return isHaveRight;
        }
        /// <summary>
        /// 操作级权限判断
        /// </summary>
        /// <param name="strModuleNo"></param>
        /// <param name="strOperateType"></param>
        /// <returns></returns>
        private bool ValidateModuleRight(string strModuleNo, string strOperateType)
        {
            IBLL.IBLL_OperatingRule operateRuleCtrl = BLLFactory.Factory.BLL_OperatingRule();
            string userId = CurrentAccount.GetUser().UserID;

            //超级管理员拥有一切权限
            if (CurrentAccount.IsSuperAdmin())
            {
                return true;
            }
            else
            {
                //访问权限验证业务逻辑...
                return operateRuleCtrl.CheckUserRule(userId, EnumParse.GetModule(strModuleNo).Value, EnumParse.GetOperateType(strOperateType).Value);
            }
        }

        /// <summary>
        /// 检查用户Session是否正常
        /// </summary>
        /// <returns></returns>
        private bool ValidateSession()
        {
            if (CurrentAccount.IsTimeout())
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 操作无权
        /// </summary>
        private void Page_NoPermission()
        {
            CurrentAccount.Goto_NoPermission();
        }

        /// <summary>
        /// 未登陆
        /// </summary>
        private void Page_NoLogin()
        {
            CurrentAccount.Goto_Login();
        }

        /// <summary>
        /// 记录系统操作日志
        /// </summary>
        /// <param name="strModuleNo"></param>
        /// <param name="strOperateType"></param>
        private void OperateLog(string strModuleNo, string strOperateType)
        {
            //周司徒实现
            try
            {
                HZ.DrugTrade.Model.KeyOperationLog log = new HZ.DrugTrade.Model.KeyOperationLog();
                log.OperateTime = DateTime.Now;
                log.OperateMessage = strModuleNo + " " + strOperateType;
                log.ClientIP = HZ.Fun.GetClientIP();//操作IP
                IBLL.IBLL_Log logCtrl = BLLFactory.Factory.BLL_Log();
                logCtrl.AddKeyOperationLog(log);
            }
            catch (Exception e)
            { }
        }

        #endregion

        #region 属性

        /// <summary>
        /// 设置模块代码，必须在子类中设置
        /// </summary>
        protected string ModuleNo
        {
            set { this._ModuleNo = value; }
            get { return this._ModuleNo; }
        }
        /// <summary>
        /// 设置 进入页面需要的操作类型
        /// </summary>
        protected string PageOperateType
        {
            set { this._OperateType = value; }
            get { return this._OperateType; }
        }
        /// <summary>
        /// 返回页面
        /// </summary>
        protected string ReturnUrl
        {
            get { return this._ReturnUrl; }
            set { this._ReturnUrl = value; }
        }
        /// <summary>
        /// 设置QueryCondition 加密串
        /// </summary>
        protected string QueryCondition
        {
            get { return this._QueryCondition; }
            set { this._QueryCondition = value; }
        }

        #endregion

        #region 保护方法
        /// <summary>
        /// 页面操作错误提示信息
        /// </summary>
        /// <param name="ErrMsg"></param>
        /// <param name="Url"></param>
        protected void PageError(string ErrMsg, string Url)
        {
            WebHint.ShowError(ErrMsg, Url);
        }

        /// <summary>
        /// 页面操作成功提示信息
        /// </summary>
        /// <param name="InfoMsg"></param>
        /// <param name="Url"></param>
        protected void PageInfo(string InfoMsg, string Url)
        {
            WebHint.ShowInfo(InfoMsg, Url);
        }

        /// <summary>
        /// 获取查询Model
        /// </summary>
        protected T GetQueryObject<T>() where T : new()
        {
            if (this._QueryCondition != "")
            {
                return StringUtility.ConvertStringToObject<T>(StringUtility.DeCompress(this._QueryCondition));
            }
            else
            {
                return default(T);
            }
        }

        /// <summary>
        /// 将给定的url加上script 实现页面跳转
        /// 针对button 的 onclintclick 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        protected string GetURLScript(string str)
        {
            int index = str.IndexOf("?");
            //给url加returnUrl,值为当前页面的Url
            if (index != -1)
            {
                str += "&" + Constants.QUERYSTRING_RETURN_URL + "=" + Page.Request.RawUrl;
            }
            else
            {
                str += "?" + Constants.QUERYSTRING_RETURN_URL + "=" + Page.Request.RawUrl;
            }
            string strScript = "if(!this.disabled){window.location='" + str + "';} return false;";
            return strScript;
        }

        #endregion

    }
}
